const fs = require('fs');
const path = require('path');
const mammoth = require('mammoth');
const pdfParse = require('pdf-parse');
const AiModelService = require('./aiModelService');

/**
 * 文档解析服务
 * 支持解析不同格式的文档
 */
class DocumentParser {
  /**
   * 根据文件类型解析文档
   * @param {string} filePath - 文件路径
   * @param {string} fileType - 文件类型 (pdf, docx, txt, html)
   * @returns {Promise<{content: string, structure: Array}>} - 解析后的内容和结构
   */
  static async parseDocument(filePath, fileType) {
    switch (fileType.toLowerCase()) {
      case 'pdf':
        return await this.parsePdf(filePath);
      case 'docx':
        return await this.parseDocx(filePath);
      case 'txt':
        return await this.parseTxt(filePath);
      case 'html':
        return await this.parseHtml(filePath);
      default:
        throw new Error(`不支持的文件类型: ${fileType}`);
    }
  }

  /**
   * 解析PDF文件
   * @param {string} filePath - PDF文件路径
   * @returns {Promise<{content: string, structure: Array}>}
   */
  static async parsePdf(filePath) {
    try {
      const dataBuffer = fs.readFileSync(filePath);
      const data = await pdfParse(dataBuffer);
      
      // 提取内容
      const content = data.text;
      
      // 使用通义千问 Qwen-Long 模型提取结构
      const structure = await this.extractStructureWithAI(content);
      
      return { content, structure };
    } catch (error) {
      throw new Error(`PDF解析错误: ${error.message}`);
    }
  }

  /**
   * 解析DOCX文件
   * @param {string} filePath - DOCX文件路径
   * @returns {Promise<{content: string, structure: Array}>}
   */
  static async parseDocx(filePath) {
    try {
      const result = await mammoth.extractRawText({ path: filePath });
      const content = result.value;
      
      // 使用通义千问 Qwen-Long 模型提取结构
      const structure = await this.extractStructureWithAI(content);
      
      return { content, structure };
    } catch (error) {
      throw new Error(`DOCX解析错误: ${error.message}`);
    }
  }

  /**
   * 解析TXT文件
   * @param {string} filePath - TXT文件路径
   * @returns {Promise<{content: string, structure: Array}>}
   */
  static async parseTxt(filePath) {
    try {
      const content = fs.readFileSync(filePath, 'utf8');
      
      // 使用通义千问 Qwen-Long 模型提取结构
      const structure = await this.extractStructureWithAI(content);
      
      return { content, structure };
    } catch (error) {
      throw new Error(`TXT解析错误: ${error.message}`);
    }
  }

  /**
   * 解析HTML文件
   * @param {string} filePath - HTML文件路径
   * @returns {Promise<{content: string, structure: Array}>}
   */
  static async parseHtml(filePath) {
    try {
      const content = fs.readFileSync(filePath, 'utf8');
      
      // 使用正则表达式移除HTML标签
      const plainText = content.replace(/<[^>]*>?/gm, '');
      
      // 使用通义千问 Qwen-Long 模型提取结构
      const structure = await this.extractStructureWithAI(plainText);
      
      return { content: plainText, structure };
    } catch (error) {
      throw new Error(`HTML解析错误: ${error.message}`);
    }
  }

  /**
   * 使用通义千问 Qwen-Long 模型从文本内容中提取文档结构
   * @param {string} content - 文档内容
   * @returns {Promise<Array>} - 结构数组
   */
  static async extractStructureWithAI(content) {
    try {
      console.log('使用通义千问 Qwen-Long 模型提取文档结构...');
      
      // 利用通义千问的大上下文窗口，提取更多内容，但仍然设置合理的限制
      const MAX_CONTENT_LENGTH = 30000; // 增加到30000字符，充分利用模型能力
      const truncatedContent = content.length > MAX_CONTENT_LENGTH ? 
        content.substring(0, MAX_CONTENT_LENGTH) + '...' : content;
      
      console.log(`原始内容长度: ${content.length}, 处理长度: ${truncatedContent.length}`);
      
      // 调用通义千问 Qwen-Long 模型
      const response = await AiModelService.parseWithQwenLong(truncatedContent, {
        task: 'extract_structure',
        temperature: 0.2, // 降低温度以获得更确定性的结果
        max_tokens: 1000  // 保持适中的输出长度
      });
      
      if (!response.success) {
        console.warn('AI 模型提取结构失败，使用传统方法提取');
        return this.extractStructure(content);
      }
      
      // 解析返回的结果
      try {
        // 获取响应文本
        let structureText = response.result;
        console.log('AI返回原始文本:', structureText.substring(0, 200) + '...');
        
        // 尝试提取JSON部分 - 增强提取能力
        let jsonData = null;
        
        // 方法1: 尝试直接解析整个响应
        try {
          jsonData = JSON.parse(structureText);
          console.log('成功直接解析JSON');
        } catch (e) {
          console.log('直接解析JSON失败，尝试提取JSON部分');
          
          // 方法2: 查找第一个 [ 和最后一个 ] 之间的内容
          const startIdx = structureText.indexOf('[');
          const endIdx = structureText.lastIndexOf(']');
          
          if (startIdx !== -1 && endIdx !== -1 && startIdx < endIdx) {
            try {
              const jsonStr = structureText.substring(startIdx, endIdx + 1);
              jsonData = JSON.parse(jsonStr);
              console.log('成功提取并解析JSON部分');
            } catch (e2) {
              console.log('提取JSON部分失败:', e2.message);
            }
          }
          
          // 方法3: 使用正则表达式尝试提取
          if (!jsonData) {
            const jsonMatch = structureText.match(/\[\s*\{[\s\S]*\}\s*\]/);
            if (jsonMatch) {
              try {
                jsonData = JSON.parse(jsonMatch[0]);
                console.log('通过正则表达式成功提取并解析JSON');
              } catch (e3) {
                console.log('正则表达式提取JSON失败:', e3.message);
              }
            }
          }
        }
        
        // 如果成功解析JSON数据
        if (jsonData && Array.isArray(jsonData) && jsonData.length > 0) {
          // 确保每个结构项都有必要的字段
          const validStructure = jsonData.filter(item => 
            item.title && 
            typeof item.startIndex === 'number' && 
            typeof item.endIndex === 'number'
          );
          
          if (validStructure.length > 0) {
            console.log(`成功提取 ${validStructure.length} 个章节结构`);
            return validStructure;
          }
        }
        
        // 如果无法解析为JSON，但响应不为空，尝试手动构建结构
        if (structureText && structureText.trim() !== '') {
          console.log('AI返回非JSON格式，尝试手动构建结构');
          
          // 尝试从文本中提取章节信息
          const manualStructure = this._extractStructureFromText(structureText, content);
          if (manualStructure && manualStructure.length > 0) {
            console.log(`手动构建了 ${manualStructure.length} 个章节结构`);
            return manualStructure;
          }
        }
        
        console.warn('无法从AI响应中提取有效结构，使用传统方法提取');
      } catch (parseError) {
        console.error('解析 AI 返回的结构时出错:', parseError);
        console.warn('使用传统方法提取结构');
      }
      
      // 如果 AI 提取失败，回退到传统方法
      return this.extractStructure(content);
    } catch (error) {
      console.error('使用 AI 提取结构时出错:', error);
      console.warn('回退到传统方法提取结构');
      return this.extractStructure(content);
    }
  }

  /**
   * 从AI返回的文本中尝试提取章节结构
   * @param {string} aiText - AI返回的文本
   * @param {string} originalContent - 原始文档内容
   * @returns {Array} - 结构数组
   */
  static _extractStructureFromText(aiText, originalContent) {
    console.log('从AI响应中提取章节结构...');
    
    // 检查是否为HTML格式
    if (aiText.includes('<!DOCTYPE html>') || aiText.includes('<html>') || aiText.includes('</html>')) {
      console.log('检测到HTML格式的响应，尝试提取纯文本...');
      // 简单地移除HTML标签
      aiText = aiText.replace(/<[^>]*>?/gm, '');
      console.log('提取后的纯文本前100字符:', aiText.substring(0, 100) + '...');
    } else if (aiText.includes('<') && aiText.includes('>')) {
      // 检查是否包含HTML标签
      console.log('检测到HTML标签，尝试提取内容...');
      aiText = aiText.replace(/<[^>]*>?/gm, '');
      console.log('提取后的纯文本前100字符:', aiText.substring(0, 100) + '...');
    }
    
    // 首先尝试从aiText中提取JSON
    try {
      const jsonMatch = aiText.match(/\[\s*\{[\s\S]*\}\s*\]/);
      if (jsonMatch) {
        const jsonStr = jsonMatch[0];
        console.log('找到可能的JSON字符串:', jsonStr.substring(0, 50) + '...');
        
        const data = JSON.parse(jsonStr);
        console.log('成功解析JSON，直接返回结构!');
        return data;
      }
    } catch (error) {
      console.log('JSON解析失败:', error.message);
    }
    
    // 如果JSON解析失败，尝试匹配常见的章节描述格式
    console.log('尝试从文本中提取章节标题...');
    
    const structure = [];
    
    // 尝试匹配常见的章节描述格式
    // 例如: "第一章: 引言", "章节1: 介绍", "1. 背景", "第1节 方法"等
    const chapterRegex = /(?:第[一二三四五六七八九十百千万]+[章节]|章节\s*\d+|[0-9]+\.\s*)[^，。:：\n]+([:：])?[^，。\n]*/g;
    
    let match;
    const matches = [];
    while ((match = chapterRegex.exec(aiText)) !== null) {
      matches.push({
        title: match[0].trim(),
        index: match.index
      });
    }
    
    console.log(`找到 ${matches.length} 个章节标题`);
    
    // 如果找到章节标题，尝试在原始内容中定位
    if (matches.length > 0) {
      for (let i = 0; i < matches.length; i++) {
        const title = matches[i].title;
        
        // 使用更灵活的标题匹配逻辑
        // 提取章节标题的关键部分，如"第一章"或"引言"
        const keyPart = title.match(/第[一二三四五六七八九十]+[章节]|[0-9]+\./)?.[0] || title.substring(0, Math.min(10, title.length));
        
        console.log(`查找章节标题关键部分: "${keyPart}"`);
        const titleIndex = originalContent.indexOf(keyPart);
        
        if (titleIndex !== -1) {
          const startIndex = titleIndex;
          // 结束索引是下一章节的开始或文档结束
          let endIndex = originalContent.length;
          if (i < matches.length - 1) {
            const nextKeyPart = matches[i + 1].title.match(/第[一二三四五六七八九十]+[章节]|[0-9]+\./)?.[0] || 
                              matches[i + 1].title.substring(0, Math.min(10, matches[i + 1].title.length));
            const nextIndex = originalContent.indexOf(nextKeyPart, startIndex);
            if (nextIndex !== -1) {
              endIndex = nextIndex;
            }
          }
          
          structure.push({
            title: title,
            startIndex: startIndex,
            endIndex: endIndex > startIndex ? endIndex : originalContent.length
          });
          
          console.log(`找到章节 "${title}" 位置: ${startIndex} - ${endIndex}`);
        } else {
          console.log(`无法在原始内容中找到章节 "${title}"`);
        }
      }
    }
    
    return structure;
  }

  /**
   * 从文本内容中提取文档结构（章节等）- 传统方法
   * @param {string} content - 文档内容
   * @returns {Array} - 结构数组
   */
  static extractStructure(content) {
    const structure = [];
    
    // 使用正则表达式匹配常见的章节标题模式
    // 例如: "第一章", "Chapter 1", "1. 介绍", "1.1 背景" 等
    const chapterRegex = /(?:^|\n)(?:第[一二三四五六七八九十百千万]+[章节]|Chapter\s+\d+|\d+\.\s+[^\n]+|\d+\.\d+\s+[^\n]+)/g;
    
    let match;
    while ((match = chapterRegex.exec(content)) !== null) {
      structure.push({
        title: match[0].trim(),
        startIndex: match.index,
        endIndex: null // 将在下一次迭代中设置
      });
      
      // 设置前一章节的结束索引
      if (structure.length > 1) {
        structure[structure.length - 2].endIndex = match.index;
      }
    }
    
    // 设置最后一章的结束索引
    if (structure.length > 0) {
      structure[structure.length - 1].endIndex = content.length;
    }
    
    return structure;
  }

  /**
   * 从文档内容中提取指定章节的内容
   * @param {string} content - 文档内容
   * @param {object} chapter - 章节信息，包含startIndex和endIndex
   * @returns {string} - 章节内容
   */
  static extractChapterContent(content, chapter) {
    if (!content || !chapter || typeof chapter.startIndex !== 'number' || typeof chapter.endIndex !== 'number') {
      console.warn('提取章节内容失败: 参数无效');
      return '';
    }
    
    try {
      return content.substring(chapter.startIndex, chapter.endIndex);
    } catch (error) {
      console.error('提取章节内容时出错:', error);
      return '';
    }
  }
}

module.exports = DocumentParser; 